#include "StdAfx.h"
ModelComponent::ModelComponent(ModelComponentDesc &desc):Actor(desc)
{
	Model=_RESC(desc.ModelName);
	bReflects=desc.bReflects;
	bRefracts=desc.bRefracts;
	DiffuseFactor=desc.DiffuseFactor;
	Owner=NULL;
}
void ModelComponent::LoadShaderVars(sptr<GameResource> shader_resc)
{

}
Pawn::Pawn(PawnDesc &desc) : Actor(desc)
{
	bKinematic=desc.bKinematic;
	bAggroed=bReturning=false;
	bVisible=desc.bVisible;
	AITarget=Vec3(0,15,0);
	for(unsigned int i=0;i<desc.ModelDescs.size();i++)
	{
		sptr<ModelComponent> model=sptr<ModelComponent>(new ModelComponent(desc.ModelDescs[i]));
		model->Owner=this;
		Models.push_back(model);
	}
	if(Models.size())
	{
		Mesh* mesh=_MESH(_MODEL(Models[0]->Model)->Mesh);
		NxBodyDesc bdesc;
		bdesc.angularDamping=0.5f;
		bdesc.linearDamping=0.5;
		if(desc.bKinematic)
			bdesc.flags = NX_BF_KINEMATIC;
		sptr<NxShapeDesc> sdesc=GetShape(Models[0]->Model);
		if(sdesc)
		{
			NxActorDesc adesc;
			adesc.shapes.push_back(sdesc.get());
			adesc.body=&bdesc;
			adesc.density=1.0f;
			adesc.globalPose.t=Pos;
			adesc.globalPose.M=(Quat)Rot;
			adesc.userData=this;

			NxSphereShapeDesc SensorDesc; 
			SensorDesc.radius = mesh->GetRadius();
			SensorDesc.localPose.t	= NxVec3(0.0f, 0.0f, 0.0f);
			SensorDesc.shapeFlags |= NX_TRIGGER_ENABLE;
			adesc.shapes.pushBack(&SensorDesc);

			physics=_MAIN_SCENE->createActor(adesc);
			
		}
		if(desc.bHasCloth)
		{
			real width=desc.ClothDimensions.x, height=desc.ClothDimensions.y, tileWidth=desc.ClothDimensions.z;
			cloth=sptr<Cloth>(new Cloth(_MAIN_SCENE, desc.ClothDesc, width, height, tileWidth));
			cloth->getNxCloth()->attachToCollidingShapes(NX_CLOTH_ATTACHMENT_TWOWAY);
			ClothMaterialResc=_RESC(desc.ClothMaterialName);
		}
	}
	bAI=desc.bAI;
	AggroRange=50;
	AIPause=3;
}
Pawn::~Pawn(void)
{
}
sptr<NxShapeDesc> Pawn::GetShape(sptr<GameResource> model_resc)
{
	Model *model=_MODEL(model_resc);
	Mesh  *mesh =_MESH(model->Mesh);
	sptr<NxShapeDesc> sdesc;
	if(model->Shape==Model::Box)
	{
		NxBoxShapeDesc *desc=new NxBoxShapeDesc();
		desc->dimensions=(mesh->vmax-mesh->vmin)/2.0f;
		sdesc=sptr<NxShapeDesc>(desc);
	}
	else if(model->Shape==Model::Sphere)
	{
		NxSphereShapeDesc *desc=new NxSphereShapeDesc();
		desc->radius=mesh->GetRadius();
		sdesc=sptr<NxShapeDesc>(desc);
	}
	else if(model->Shape==Model::Cylinder)
	{
		NxCapsuleShapeDesc *desc=new NxCapsuleShapeDesc();
		desc->radius=mesh->vmax.x;
		desc->height=mesh->vmax.y-mesh->vmin.y-desc->radius*2;
		sdesc=sptr<NxShapeDesc>(desc);
	}

	return sdesc;
}
void Pawn::Update(double dt)
{
	AIPause-=dt;
	if(physics)
	{
		if(bKinematic&&bAI&&AIPause<=0.0)
		{
			Vec3 dir=AITarget-physics->getGlobalPosition();
			dir.y=0;
			if(dir.magnitude()>50.0*dt)
			{
				dir.normalize();
				physics->moveGlobalPosition(physics->getGlobalPosition()+dir*50.0*dt);
			}
			else physics->moveGlobalPosition(Vec3(AITarget.x, physics->getGlobalPosition().y, AITarget.z));
		}
		Pos=physics->getGlobalPose().t;
		quat=physics->getGlobalOrientationQuat();
	}
	else quat=(Quat)Rot;
}
void Pawn::AI()
{
	Pawn* player=_PLAYER;
	Vec3 dir=player->Pos-physics->getGlobalPosition();

	if(dir.magnitude()<AggroRange)
	{
		dir.y=0;
		dir.normalize();
		AITarget=player->Pos;
		AITarget.y=0;
		bAggroed=true;
		ClothMaterialResc=_RESC("RageGhostMat");
	}
	else if(AIPause<=0)
	{
		if(bAggroed)
		{
			AITarget=Vec3(0,0,0);
			bAggroed=false;
			bReturning=true;
			ClothMaterialResc=_RESC("LoneGhostMat");
		}
		else if(!bReturning) ClothMaterialResc=_RESC("MegustaGhostMat");
		float lambda=3.0f;
		Vec3 dir=AITarget-Pos;
		dir.y=0;
		float distance=dir.magnitude();
		if(distance<lambda)
		{
			float angle=2*PI*(float)std::rand()/(float)RAND_MAX;
			AITarget=Vec3(std::sin(angle), 0, std::cos(angle))*50.0;
			AIPause=1.0;
			bReturning=false;
			ClothMaterialResc=_RESC("TrollGhostMat");
		}
	}
	else ClothMaterialResc=_RESC("TrollGhostMat");
}
void Pawn::React(Pawn* pawn)
{
	if(Name==string("PacMan"))
	{
		if(pawn->Name==string("Pellet"))
		{
			pawn->bVisible=false;
		}
		else if(pawn->Name==string("Ghostie"))
		{
			Vec3 dir=Pos-pawn->Pos;
			dir.y=0;
			dir.normalize();
			physics->setLinearVelocity(dir*100.0);
		}
	}
}

